package megrez.bussiness.system.service;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.TreeMap;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import lombok.RequiredArgsConstructor;
import megrez.bussiness.system.entity.Dept;
import megrez.bussiness.system.repository.DeptRepository;
import megrez.bussiness.system.util.SystemErrorCode;
import megrez.bussiness.system.util.SystemException;
import megrez.common.util.EntityMissingException;

/**
 * 部门服务
 * 
 * @author Lucky Yang
 * @since 0.0.1
 */
@Service
@RequiredArgsConstructor
public class DeptService {
    private final DeptRepository deptRepository;

    @Transactional(rollbackFor = Exception.class)
    public Dept save(Long parentId, Dept dept) {
        Optional.ofNullable(parentId).map(id -> this.findById(parentId)).ifPresent(p -> {
            dept.setParent(p);
            if (Boolean.TRUE.equals(p.getIsLeaf())) {
                p.setIsLeaf(false);
                deptRepository.save(p);
            }
        });

        return deptRepository.save(dept);
    }

    @Transactional(rollbackFor = Exception.class)
    public Dept update(Long id, Dept dept) {
        Dept entity = this.findById(id);
        entity.copy(dept);
        return deptRepository.save(entity);

    }

    @Transactional(rollbackFor = Exception.class)
    public void delete(Long deptId) {
        deptRepository.findById(deptId).ifPresent(dept -> {
            if (deptRepository.countByParent(dept) > 0) {
                throw new SystemException(SystemErrorCode.DELETE_DEPT_HAS_CHILD);
            }

            deptRepository.delete(dept);
        });

    }

    public Dept findById(Long id) {
        return deptRepository.findById(id).orElseThrow(EntityMissingException::new);
    }

    /**
     * 获取所有部门全称， key=code, value=全称
     * 
     * @return
     */
    public Map<String, String> getCodeNameMap() {
        List<Dept> allDeptList = deptRepository.findAll();
        // key=code, value=名称
        Map<String, String> allDeptMap = allDeptList.stream().collect(Collectors.toMap(Dept::getCode, Dept::getName));

        Map<String, String> rslt = new TreeMap<>();
        allDeptList.stream()
                // 排序
                .sorted(Comparator.comparing(Dept::getPathCode))
                .forEachOrdered(d -> {
                    String value = Stream.of(d.getPathCode().split(Dept.PATH_SEP))
                            .map(allDeptMap::get)
                            .collect(Collectors.joining(Dept.PATH_SEP));
                    rslt.put(d.getCode(), value);
                });

        return rslt;
    }

    /**
     * 查询所有下级
     * 
     * @param id 主键
     * @return
     */
    public List<Dept> getGrandchildren(Long id) {
        Dept parent = this.findById(id);
        List<Dept> entities = deptRepository.findByPathCodeLike(parent.getPathCode() + Dept.PATH_SEP + "%");
        Collections.sort(entities, Comparator.comparing(Dept::getPathCode));
        return entities;
    }
}
